%name lex_pattern_

%include {
    global $CFG;
    require_once($CFG->dirroot . '/blocks/formal_langs/tokens_base.php');
    require_once($CFG->dirroot . '/blocks/formal_langs/lexical_pattern.php');
}

%include_class {
    public $error;
    public $list = array();
    public $token_list = array();
    public $conditions = array('INITIAL');
    public $success = false;

    public $dump_info = '';

    private $debug_mode = false;
    private $pattern_num = 0;

    public function dump() {
        if ($this->debug_mode) {
            ob_start();
            $this->dump_info .= "<pre>Stack dump:\n";
            var_dump($this->yystack);
            $this->dump_info .= ob_get_contents();
            ob_end_clean();

            ob_start();
            $this->dump_info .= "$this->list dump:\n";
            var_dump($this->ast);
            $this->dump_info .= ob_get_contents();
            ob_end_clean();

            ob_start();
            $this->dump_info .= "$this->error dump:\n";
            var_dump($this->error);
            $this->dump_info .= ob_get_contents();
            ob_end_clean();
            $this->dump_indo .= "</pre>";
        }
    }

    public function process_token($token) {
        $this->doParse($token->type(), $token);
    }

    private function add_condition($condition) {
        if (in_array($condition, $this->conditions)) {
        } else {
            array_push($this->conditions, $condition);
        }
    }

    private function make_token_list() {
        if (count($this->list) > 0) {
            foreach($this->list as $p) {
                if (in_array($p->name(), $this->token_list)) {
                } else {
                    array_push($this->token_list, $p->name());
                }
            }
        }
    }
}

%parse_failure {
    if ($this->debug_mode) {
        $this->dump_info .= "Parsing error.\n";
        $this->dump();
    }
    $this->success = false;
 }

%parse_accept {
    if ($this->debug_mode) {
        $this->dump_info .= "Parsing done.\n";
        $this->dump();
    }
    $this->success = true;
 }

%syntax_error {
    if ($this->debug_mode) {
        $this->dump_info .= "Syntax error.\n";
    }
 }

start ::= patterns(B) . {
    $this->list = B;
}

patterns(A) ::= pattern(B) . {
    A = array();
    A[] = B;
}
patterns(A) ::= patterns(B) pattern(C) . {
    B[] = C;
    A = B;
}

pattern(A) ::= ID(B) REGEXP(C) ID(D) ARROW ID(E) EQUAL actions(F) SEMICOLON . {
    $res = new block_formal_langs_lexer_pattern($this->pattern_num++,B, C, F, D, E);
    A = $res;
    $this->add_condition(D);
    $this->add_condition(E);
}
pattern(A) ::= ID(B) REGEXP(C) ID(D) ARROW ID(E)                  SEMICOLON . {
    $res = new block_formal_langs_lexer_pattern($this->pattern_num++,B, C, NULL, D, E);
    A = $res;
    $this->add_condition(D);
    $this->add_condition(E);
}
pattern(A) ::= ID(B) REGEXP(C)       ARROW ID(E) EQUAL actions(F) SEMICOLON . {
    $res = new block_formal_langs_lexer_pattern($this->pattern_num++,B, C, F, 'INITIAL', E);    
    A = $res;
    $this->add_condition(E);
}
pattern(A) ::= ID(B) REGEXP(C)       ARROW ID(E)                  SEMICOLON . {
    $res = new block_formal_langs_lexer_pattern($this->pattern_num++,B, C, NULL, 'INITIAL', E);    
    A = $res;
    $this->add_condition(E);
}
pattern(A) ::= ID(B) REGEXP(C) ID(D)             EQUAL actions(F) SEMICOLON . {
    $res = new block_formal_langs_lexer_pattern($this->pattern_num++,B, C, F, D);
    A = $res;
    $this->add_condition(D);
}
pattern(A) ::= ID(B) REGEXP(C) ID(D)                              SEMICOLON . {
    $res = new block_formal_langs_lexer_pattern($this->pattern_num++,B, C, NULL, D);
    A = $res;
    $this->add_condition(D);
}
pattern(A) ::= ID(B) REGEXP(C)                   EQUAL actions(F) SEMICOLON . {
    $res = new block_formal_langs_lexer_pattern($this->pattern_num++,B, C, F);
    A = $res;
}
pattern(A) ::= ID(B) REGEXP(C)                                    SEMICOLON . {
    $res = new block_formal_langs_lexer_pattern($this->pattern_num++,B, C, NULL);
    A = $res;
}

actions(A) ::= action(B) . {
    A = array();
    A[] = B;
}
actions(A) ::= actions(B) action(C) . {
    B[] = C;
    A = B;
}

action(A) ::= COPY . {
    A = new block_formal_langs_lexer_action('copy');
}
action(A) ::= CREATE . {
    A = new block_formal_langs_lexer_action('create');
}
action(A) ::= APPEND . {
    A = new block_formal_langs_lexer_action('append');
}
action(A) ::= ERROR LPAREN REGEXP(C) RPAREN . {
    A = new block_formal_langs_lexer_action('error', C);
}

